import Cesium from '../Ces/Cesium'
import pako from 'pako'

const sizeOfUint32 = Uint32Array.BYTES_PER_ELEMENT

function parsew3dm(arrayBuffer) {
  let byteOffset = 0
  const uint8Array = arrayBuffer instanceof Uint8Array ? arrayBuffer : new Uint8Array(arrayBuffer)
  const view = new DataView(uint8Array.buffer)

  byteOffset += sizeOfUint32 // Skip magic
  const version = view.getUint32(byteOffset, true)

  if (version > 2) {
    throw new Cesium.RuntimeError(
      'Only Weather 3d model version 1 or 2 is supported.  Version '
      + version
      + ' is not.',
    )
  }
  byteOffset += sizeOfUint32

  // Skip byteLength
  byteOffset += sizeOfUint32

  const featureTableJsonByteLength = view.getUint32(byteOffset, true)

  if (featureTableJsonByteLength === 0) {
    throw new Cesium.RuntimeError(
      'Feature table must have a byte length greater than zero',
    )
  }
  byteOffset += sizeOfUint32
  const featureTableBinaryByteLength = view.getUint32(byteOffset, true)

  byteOffset += sizeOfUint32
  const featureTableString = Cesium.getStringFromTypedArray(
    uint8Array,
    byteOffset,
    featureTableJsonByteLength,
  )
  const featureTableJson = JSON.parse(featureTableString)

  byteOffset += featureTableJsonByteLength

  let featureTableBinary

  const { width, depth, height, pixelFormat, pixelType, pixelDatatype } = featureTableJson.source
  const comp = Cesium.PixelFormat.componentsLength(pixelFormat)
  const perByte = Cesium.PixelDatatype.sizeInBytes(pixelDatatype | pixelType)
  const numComponent = width * depth * height

  if (featureTableJson.source.pixelDatatype === Cesium.PixelDatatype.FLOAT) {
    const padding = byteOffset % 4
    if (padding === 0) {
      featureTableBinary = new Float32Array(
        uint8Array.buffer, byteOffset,
        featureTableBinaryByteLength / 4)
    } else {
      console.log(`padding is ${padding}`)
      featureTableBinary = new Float32Array(
        uint8Array.slice(byteOffset).buffer, 0,
        featureTableBinaryByteLength / 4,
      )
    }

  } else if (featureTableJson.source.pixelDatatype === Cesium.PixelDatatype.HALF_FLOAT) {
    const padding = byteOffset % 4
    if (padding === 0) {
      featureTableBinary = new Uint16Array(
        uint8Array.buffer, byteOffset,
        featureTableBinaryByteLength / 2)
    } else {
      console.log(`padding is ${padding}`)
      featureTableBinary = new Uint16Array(
        uint8Array.slice(byteOffset).buffer, 0,
        featureTableBinaryByteLength / 2,
      )
    }

  } else {
    featureTableBinary = new Uint8Array(
      uint8Array.buffer,
      byteOffset,
      featureTableBinaryByteLength,
    )
    byteOffset += featureTableBinaryByteLength
  }

  const isCompressed =
    featureTableJson.source.pixelDatatype === Cesium.PixelDatatype.UNSIGNED_BYTE
    && featureTableBinary.length !== (numComponent * comp * perByte)
  if (isCompressed) {
    featureTableJson.source.arrayBufferView = pako.inflateRaw(featureTableBinary)
  } else {
    featureTableJson.source.arrayBufferView = featureTableBinary
  }

  return featureTableJson
}

class WeatherData {
  static parseW3dm(blob) {
    const uint8Array = new Uint8Array(blob, 0, 4)

    // w3dm
    if (uint8Array[0] !== 119
      && uint8Array[1] !== 51
      && uint8Array[2] !== 100
      && uint8Array[3] !== 109) {
      return parsew3dm(pako.ungzip(blob))
    }

    return parsew3dm(blob)
  }
}


export default WeatherData
